package data.render;

import java.awt.Color;

import control.profiler.Profiler;

import data.base.Material;
import data.base.PointLight;
import data.base.Vector3;
import data.complex.Boundary;
import data.complex.Ray;
import data.complex.Triangle;
import data.complex.VoxelSpace;
import data.hierarchy.Mesh;
import data.hierarchy.TriangleGroup;
import data.hierarchy.World;



public class FastShadowPhongRenderMethod implements IRenderMethod{
  private World world;
  private VoxelSpace vs;
  
  public FastShadowPhongRenderMethod(World world){
    this.world = world;
    Profiler.getInstance().record("Initializing Voxelspace...");
    vs = new VoxelSpace(new Boundary(world));
    refresh();
    Profiler.getInstance().putMessage("Vertices: " + vs.getVertexCount());
    Profiler.getInstance().putMessage("Triangles: " + vs.getTriangleCount());
    Profiler.getInstance().display();
  }
  
  public void refresh(){
    for(Mesh m : world.getMeshes())
      for(TriangleGroup tg : m)
        for(Triangle t : tg)
          vs.registerTriangle(t);
  }

  @Override
  public Color getPixel(Ray ray) {
    vs.calculateFirstTriangleIntersection(ray, Double.MAX_VALUE, null);
    if(ray.getIntersection().isIntersecting()){
      int red = 0;
      int green = 0;
      int blue = 0;
      float matR = 1;
      float matG = 1;
      float matB = 1;
      Material mat = ray.getIntersection().getTriangle().getGroup().getMaterial();
      if(mat != null){
        Color c = mat.getColorAt(ray.getIntersection().getTextureCoordinate());
        matR = (float)c.getRed() / 255;
        matG = (float)c.getGreen() / 255;
        matB = (float)c.getBlue() / 255;
      }
      for(PointLight light : world.getPointLights()){
        Ray toLight = new Ray(ray.getIntersection());
        toLight.setTarget(light);
        double maxDist = toLight.getLength();
        vs.calculateFirstTriangleIntersection(toLight, maxDist, ray.getIntersection().getTriangle());
        if(!toLight.getIntersection().isIntersecting()){
          Vector3 a = new Vector3(ray.getIntersection(), light);
          a.normalize();
          double brightness = 
            Math.max(0, a.getDotProduct(ray.getIntersection().getNormal())) *
            light.getIntensity();
          red += light.getColor().getRed() * brightness;
          green += light.getColor().getGreen() * brightness;
          blue += light.getColor().getBlue() * brightness;
        }
      }
      return new Color(
          Math.min(255, (int)(red * matR)),
          Math.min(255, (int)(green * matG)),
          Math.min(255, (int)(blue * matB)));
    }
    return Color.BLACK;
  }
  
  public VoxelSpace getVoxelSpace(){
    return vs;
  }
}
